package com.mstar.cameracapturetest;

import com.mstar.cameracapturetest.R;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import android.app.Activity;
import android.graphics.Bitmap;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.DropBoxManager.Entry;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Spinner;

public class CameraCapture extends Activity {
	private static final String TAG = CameraCapture.class.getSimpleName();

	private static final int M_HANDLER_SHOW_IMAGE = 0;
	private static final int M_HANDLER_SHOW_LONG = 1;
	private static final int M_HANDLER_TIMEOUT = 2;

	private RelativeLayout mParentContainer = null;
	private Button mCapBtn = null;
	private ImageView mCapImgView = null;
	
	private List<String> mResolutionList = new ArrayList<String>();   
	private Spinner mResolutionSpn = null;    
    private ArrayAdapter<String> mResAdapter = null;
    private HashMap<String, ArrayList<Integer>> mReslosutionMap = new HashMap<String , ArrayList<Integer>>(); 
    private List<String> mModeList = new ArrayList<String>();
    private Spinner mModeSpn = null;
    private ArrayAdapter<String> mModeAdapter = null;
    private HashMap<String, Integer> mModeMap = new HashMap<String, Integer>(); 
    private AdapterView.OnItemSelectedListener mSpinnerListener = null;
    
	private Camera mCamera = null;
	private Parameters mParameters = null;
	private int mWidth = 640;
	private int mHeight = 480;
	private int mTravelingRes = MCamera.Parameters.E_TRAVELING_RES_640_480;
	private int mTravelingMode = MCamera.Parameters.E_TRAVELING_ALL_VIDEO_WITH_OSD;
	private CapturePicCallback mCallback = null;
	private View.OnClickListener mOnClickListener = null;
	private Handler mHandler = null;
	
	private boolean mStartPreview = false;

	public CameraCapture() {

		mOnClickListener = new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// Perform action on click
				switch (v.getId()) {
				case R.id.capture:
					if(false == mStartPreview){
						mStartPreview = true;
						mParentContainer.setVisibility(View.INVISIBLE);
						
						startCamera();
						takePicture(mWidth, mHeight, MCamera.Parameters.E_TRAVELING_MEM_FORMAT_ABGR8888);
					}
					break;
					
				default:
					break;
				}
			}
		};

		mHandler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				Log.d(TAG, "mHandler handlerMessage! message what: " + msg.what);

				switch (msg.what) {
				case M_HANDLER_SHOW_IMAGE:
					if (mCamera != null)  {
			            try{
			            	if(true == mStartPreview){
			            		mHandler.removeMessages(M_HANDLER_TIMEOUT);
			            		mCamera.stopPreview();
			            		mStartPreview = false;
			            		mParentContainer.setVisibility(View.VISIBLE);
			            		
			            		StopCamera();
			            	}
			            } catch (Exception e){
			            	Log.e(TAG, "M_HANDLE_SHOW_IMAGE stop failed.");
			                e.printStackTrace();
			            }
			        }
					
					mCapImgView.setImageBitmap((Bitmap) msg.obj);
					break;
					
				case M_HANDLER_SHOW_LONG:
					break;
					
				case M_HANDLER_TIMEOUT:
					try{
						if(true == mStartPreview){
							mCamera.stopPreview();
							mStartPreview = false;
							mParentContainer.setVisibility(View.VISIBLE);
							StopCamera();
						}
					} catch (Exception e){
						Log.e(TAG, "M_HANDLE_SHOW_IMAGE stop failed.");
						e.printStackTrace();
					}
					break;
					
				default:
					break;
				}
				super.handleMessage(msg);
			}
		};
		
		mSpinnerListener = new AdapterView.OnItemSelectedListener() {    
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {    
        		
            	switch (parent.getId()) {
				case R.id.traveling_res:
					String resStr = mResAdapter.getItem(position);
					Log.d(TAG, "resStr = " + resStr);
					mTravelingRes = mReslosutionMap.get(resStr).get(0);
					mWidth = mReslosutionMap.get(resStr).get(1);
					mHeight = mReslosutionMap.get(resStr).get(2);
					Log.d(TAG, "mSpinnerListener. Traveling resolution: " + mTravelingRes + 
							"; width: " + mWidth + "; height: " + mHeight +
							"; position: " + position);
					break;
				
				case R.id.traveling_mode:
					String modeStr = mModeAdapter.getItem(position);
					mTravelingMode = mModeMap.get(modeStr);
					Log.d(TAG, "mSpinnerListener. Traveling mode: " + mTravelingMode +
							"; position: " + position);
					break;
					
				default:
					break;
				}
            	
            	parent.setVisibility(View.VISIBLE);    
            }    
            public void onNothingSelected(AdapterView<?> parent) {    
                // TODO Auto-generated method stub    
            	parent.setVisibility(View.VISIBLE);    
            }    
        };

	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_image_capture);
		
		mParentContainer = (RelativeLayout)findViewById(R.id.parent_container);
		
		mCapBtn = (Button) findViewById(R.id.capture);
		
		mCapImgView = (ImageView) findViewById(R.id.capture_image);
		mCapBtn.setOnClickListener(mOnClickListener);
		
		mResolutionSpn = (Spinner) findViewById(R.id.traveling_res);
		mModeSpn = (Spinner) findViewById(R.id.traveling_mode);
		setResolutionSpn();
		setModeSpn();
	}

	@Override
	protected void onDestroy() {

		super.onDestroy();
	}

	@Override
	protected void onStart() {

		//startCamera();
		super.onStart();
	}

	@Override
	protected void onStop() {

		//StopCamera();
		super.onStop();
	}

	public void startCamera() {
		try {
			mCamera = Camera.open(5);
			mCallback = new CapturePicCallback(this.mCamera, this.mHandler, -1, -1);
		} catch (Exception e) {
			Log.e(TAG, "startCamera Exception +++++++++");
			e.printStackTrace();
		}

		return;
	}

	public void StopCamera() {
		try {
			Log.d(TAG, "stop camera -------------");
			
	            try
	            {
	            	if(true == mStartPreview){
	            		mCamera.stopPreview();
	            	}
	                mCamera.setPreviewDisplay(null);
	                mCamera.release();
	            } catch (Exception e){
	                e.printStackTrace();
	            }
		} catch (Exception e) {
			Log.e(TAG, "stop camera Exception -------------S-");
			e.printStackTrace();
		}

		return;
	}

	public void takePicture(int width, int height, int memFormat) {
		
		int bufferSize = 0;
		switch(memFormat){
		case MCamera.Parameters.E_TRAVELING_MEM_FORMAT_YUV422_YUYV:
			bufferSize = width * height * 2;
			break;
			
		case MCamera.Parameters.E_TRAVELING_MEM_FORMAT_ABGR8888:
			bufferSize = width * height * 4;
			break;
		case MCamera.Parameters.E_TRAVELING_MEM_FORMAT_YC420:
			//bufferSize = width * height * 3 / 2;
			//framesize = width * CEILING_ALIGN(height,DIP_ALIGNMENT_YH_FACTOR); //Y size 16  1920*1088
			//framesize += width * CEILING_ALIGN(height,DIP_ALIGNMENT_CH_FACTOR) * 1/2; //C size 32  1920*544
			bufferSize = 1920 * 1088 + 1920 * 544;
			break;
			
		default:
			break;
		}
		
		byte[] callbackBuffer = new byte[bufferSize]; // ABGR8888 1920*1080*4
		callbackBuffer[bufferSize - 1] = 0;
		
		Log.d(TAG, "takePicture. Traveling resolution: " + mTravelingRes + 
				"; Traveling mode: " + mTravelingMode +
				"; width: " + width + "; height: " + height);
		mParameters = mCamera.getParameters();
		mParameters.setPictureSize(width, height);
		mParameters.setPreviewSize(width, height);

		mParameters.set("traveling-res", mTravelingRes);
		mParameters.set("traveling-mode",  mTravelingMode);
		mParameters.set("traveling-mem-format", memFormat);  	//MCamera.Parameters.E_TRAVELING_MEM_FORMAT_ABGR8888
		mParameters.set("traveling-frame-rate", 0);
		mCamera.setParameters(mParameters);
		
		try {
	        final Method addRawImageCallbackBuffer =
	                mCamera.getClass()
	                       .getDeclaredMethod("addRawImageCallbackBuffer",
	                                          byte[].class);
	        addRawImageCallbackBuffer.invoke(mCamera, callbackBuffer);
	    } catch (Exception e) {
	        Log.e(TAG, "Add raw image callback buffer error.", e);
	    }
		
		mCallback.setPicMemFormat(memFormat);
		mCallback.setPicFrameRate(0);
		mCallback.setResolution(width, height);
		mCallback.setTravelingMode(mTravelingMode);
		
		try{
			mCamera.startPreview();
			mCamera.takePicture(null, mCallback, null);
		} catch (Exception e){
			Log.e(TAG, "startPreview or takePicture fail.");
			e.printStackTrace();
		}
		
		Message msg = Message.obtain();
		msg.what = M_HANDLER_TIMEOUT;
		mHandler.sendMessageDelayed(msg, 1000);
	}

	private void setResolutionSpn(){
		mResolutionList.add("480P");
		mResolutionList.add("720P");
		mResolutionList.add("1080P");
		
		ArrayList<Integer> al0 = new ArrayList<Integer>(3);
		al0.add(MCamera.Parameters.E_TRAVELING_RES_640_480);
		al0.add(640);
		al0.add(480);
		mReslosutionMap.put("480P", al0);
		
		ArrayList<Integer> al1 = new ArrayList<Integer>(3);
		al1.add(MCamera.Parameters.E_TRAVELING_RES_1920_1080);
		al1.add(1920);
		al1.add(1080);
		mReslosutionMap.put("1080P", al1);
		
		ArrayList<Integer> al2 = new ArrayList<Integer>(3);
		al2.add(0, MCamera.Parameters.E_TRAVELING_RES_1280_720);
		al2.add(1280);
		al2.add(720);
		mReslosutionMap.put("720P", al2);
		
		mResAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, mResolutionList);
		mResAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		mResolutionSpn.setAdapter(mResAdapter);
		mResolutionSpn.setOnItemSelectedListener(mSpinnerListener);
		
//		java.util.Iterator it = mReslosutionMap.entrySet().iterator();
//		Log.d(TAG, "mResolution size =" + mReslosutionMap.size());
//		while(it.hasNext()){
//			java.util.Map.Entry entry = (java.util.Map.Entry)it.next();
//			ArrayList<Integer> item = (ArrayList<Integer>)entry.getValue();
//			Log.d(TAG, "mResolutionMap key = " + entry.getKey() +
//					"; 0: " + item.get(0) + 
//					"; 1: " + item.get(1) +
//					"; 2: " + item.get(2));
//		}
	}

	private void setModeSpn(){
		mModeList.add("WithOSD");
		mModeList.add("WithOutOSD");
		mModeList.add("main");
		mModeMap.put("WithOSD", MCamera.Parameters.E_TRAVELING_ALL_VIDEO_WITH_OSD);
		mModeMap.put("WithOutOSD", MCamera.Parameters.E_TRAVELING_ALL_VIDEO);
		mModeMap.put("main", MCamera.Parameters.E_TRAVELING_1ST_VIDEO_PROGRESSIVE_AUTO);
		
		
		mModeAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, mModeList);
		mModeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		mModeSpn.setAdapter(mModeAdapter);
		mModeSpn.setOnItemSelectedListener(mSpinnerListener);
	}
}
